<template>
  <div class="form-input">
    <!-- 标签 -->
    <div v-if="label" class="input-label">
      <span class="label-text">{{ label }}</span>
      <span v-if="required" class="required-mark">*</span>
      <el-tooltip v-if="tooltip" :content="tooltip" placement="top">
        <el-icon class="tooltip-icon"><QuestionFilled /></el-icon>
      </el-tooltip>
    </div>

    <!-- 输入框 -->
    <div class="input-wrapper" :class="{ 'has-error': hasError }">
      <el-input
        v-model="inputValue"
        v-bind="$attrs"
        :type="type"
        :placeholder="placeholder"
        :disabled="disabled"
        :readonly="readonly"
        :maxlength="maxlength"
        :show-word-limit="showWordLimit"
        :show-password="type === 'password'"
        :clearable="clearable"
        @input="handleInput"
        @change="handleChange"
        @blur="handleBlur"
        @focus="handleFocus"
      >
        <!-- 前缀图标 -->
        <template v-if="prefixIcon" #prefix>
          <el-icon><component :is="prefixIcon" /></el-icon>
        </template>

        <!-- 后缀图标 -->
        <template v-if="suffixIcon" #suffix>
          <el-icon><component :is="suffixIcon" /></el-icon>
        </template>

        <!-- 前置内容 -->
        <template v-if="$slots.prepend" #prepend>
          <slot name="prepend" />
        </template>

        <!-- 后置内容 -->
        <template v-if="$slots.append" #append>
          <slot name="append" />
        </template>
      </el-input>

      <!-- 验证错误信息 -->
      <div v-if="hasError" class="error-message">
        {{ errorMessage }}
      </div>

      <!-- 帮助文本 -->
      <div v-if="helpText && !hasError" class="help-text">
        {{ helpText }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch } from "vue";
import { QuestionFilled } from "@element-plus/icons-vue";

const props = defineProps({
  modelValue: {
    type: [String, Number],
    default: "",
  },
  label: {
    type: String,
    default: "",
  },
  type: {
    type: String,
    default: "text",
    validator: (value) =>
      [
        "text",
        "textarea",
        "password",
        "number",
        "email",
        "tel",
        "url",
      ].includes(value),
  },
  placeholder: {
    type: String,
    default: "",
  },
  required: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  readonly: {
    type: Boolean,
    default: false,
  },
  clearable: {
    type: Boolean,
    default: true,
  },
  maxlength: {
    type: Number,
    default: undefined,
  },
  showWordLimit: {
    type: Boolean,
    default: false,
  },
  prefixIcon: {
    type: [String, Object],
    default: "",
  },
  suffixIcon: {
    type: [String, Object],
    default: "",
  },
  tooltip: {
    type: String,
    default: "",
  },
  helpText: {
    type: String,
    default: "",
  },
  rules: {
    type: Array,
    default: () => [],
  },
  validateOnInput: {
    type: Boolean,
    default: false,
  },
  validateOnBlur: {
    type: Boolean,
    default: true,
  },
});

const emit = defineEmits([
  "update:modelValue",
  "input",
  "change",
  "blur",
  "focus",
  "error",
  "valid",
]);

const inputValue = computed({
  get: () => props.modelValue,
  set: (value) => emit("update:modelValue", value),
});

const errorMessage = ref("");
const hasError = computed(() => !!errorMessage.value);

// 验证输入值
const validate = (value) => {
  if (!props.rules.length) return true;

  for (const rule of props.rules) {
    if (rule.required && !value) {
      errorMessage.value = rule.message || "此项为必填项";
      return false;
    }

    if (rule.pattern && !rule.pattern.test(value)) {
      errorMessage.value = rule.message || "输入格式不正确";
      return false;
    }

    if (rule.validator) {
      try {
        const result = rule.validator(value);
        if (result !== true) {
          errorMessage.value = result || "验证失败";
          return false;
        }
      } catch (error) {
        errorMessage.value = error.message || "验证失败";
        return false;
      }
    }
  }

  errorMessage.value = "";
  return true;
};

// 处理输入
const handleInput = (value) => {
  emit("input", value);
  if (props.validateOnInput) {
    const isValid = validate(value);
    emit(isValid ? "valid" : "error", errorMessage.value);
  }
};

// 处理变更
const handleChange = (value) => {
  emit("change", value);
};

// 处理失焦
const handleBlur = (event) => {
  emit("blur", event);
  if (props.validateOnBlur) {
    const isValid = validate(inputValue.value);
    emit(isValid ? "valid" : "error", errorMessage.value);
  }
};

// 处理聚焦
const handleFocus = (event) => {
  emit("focus", event);
};

// 监听值变化
watch(
  () => props.modelValue,
  (newValue) => {
    if (props.validateOnInput || props.validateOnBlur) {
      const isValid = validate(newValue);
      emit(isValid ? "valid" : "error", errorMessage.value);
    }
  },
);
</script>

<style lang="scss" scoped>
.form-input {
  @apply mb-4;

  .input-label {
    @apply flex items-center mb-1;

    .label-text {
      @apply text-sm text-gray-700 font-medium;
    }

    .required-mark {
      @apply text-red-500 ml-1;
    }

    .tooltip-icon {
      @apply ml-1 text-gray-400 cursor-help;
    }
  }

  .input-wrapper {
    @apply relative;

    &.has-error {
      :deep(.el-input__wrapper) {
        @apply border-red-500 hover:border-red-500 focus:border-red-500;
        box-shadow: 0 0 0 1px var(--el-color-danger) inset;
      }
    }

    .error-message {
      @apply mt-1 text-sm text-red-500;
    }

    .help-text {
      @apply mt-1 text-sm text-gray-500;
    }
  }
}
</style>
